package com.thingcom.delinrobot.Data;

import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import com.gizwits.gizwifisdk.api.GizWifiDevice;
import com.gizwits.gizwifisdk.api.GizWifiSDK;
import com.gizwits.gizwifisdk.enumration.GizWifiDeviceNetStatus;
import com.gizwits.gizwifisdk.enumration.GizWifiErrorCode;
import com.gizwits.gizwifisdk.listener.GizWifiDeviceListener;
import com.thingcom.delinrobot.utils.HexStrUtils;
import com.thingcom.delinrobot.utils.HexUtil;
import com.thingcom.delinrobot.utils.MyLog;

import java.util.concurrent.ConcurrentHashMap;

import static com.thingcom.delinrobot.DelinApplication.PRODUCT_S;

/**
 * author : YuFeng
 * e-mail : 923462992@qq.com
 * date   : 2019/12/19
 */
public class GizManger {

    private static final String TAG = "GizManger";
    private Toast mToast;
    private GizWifiDevice mDevice;
    private Context mContext;
    ConcurrentHashMap<String, Object> dataMap = new ConcurrentHashMap<String, Object>();

    /*
     * ===========================================================
     * 以下key值对应开发者在云端定义的数据点标识名
     * ===========================================================
     */
    // 数据点"Stop"对应的标识名
    private static final String KEY_STOP = "Stop";
    // 数据点"Home"对应的标识名
    private static final String KEY_HOME = "Home";
    // 数据点"WorkingArea"对应的标识名
    private static final String KEY_WORKINGAREA = "workingArea";
    // 数据点"Language"对应的标识名
    private static final String KEY_LANGUAGE = "Language";
    // 数据点"WorkingTime"对应的标识名
    private static final String KEY_WORKINGTIME = "WorkingTime";
    // 数据点"CurrentTime"对应的标识名
    private static final String KEY_CURRENTTIME = "CurrentTime";
    // 数据点"PIN"对应的标识名
    private static final String KEY_PIN = "PIN";
    // 数据点"Power"对应的标识名
    private static final String KEY_POWER = "Power";
    // 数据点"Error"对应的标识名
    private static final String KEY_ERROR = "Error";
    // 数据点"RobotState"对应的标识名
    private static final String KEY_ROBOTSTATE = "RobotState";

    /*
     * ===========================================================
     * 以下变量对应设备上报类型为布尔、数值、扩展数据点的数据存储
     * ===========================================================
     */
    // 数据点"Stop"对应的存储数据
    public static boolean data_Stop;
    // 数据点"Home"对应的存储数据
    public static boolean data_Home;
    // 数据点"WorkingArea"对应的存储数据
    public static int data_workingArea;
    // 数据点"Language"对应的存储数据
    public static int data_Language;
    // 数据点"WorkingTime"对应的存储数据
    public static byte[] data_WorkingTime;
    // 数据点"CurrentTime"对应的存储数据
    public static byte[] data_CurrentTime;
    // 数据点"PIN"对应的存储数据
    public static byte[] data_PIN;
    // 数据点"Power"对应的存储数据
    public static int data_Power;
    // 数据点"Error"对应的存储数据
    public static int data_Error;
    // 数据点"RobotState"对应的存储数据
    public static int data_RobotState;

    //静态内部类
    //优雅，实现了懒加载和线程安全，线程安全利用了虚拟机的机制
    private static class GizHolder{
        public static final GizManger instance = new GizManger();
    }

    public static GizManger getInstance() {
        return GizHolder.instance;
    }

    private GizManger() {}

    public void init(Context context) {
        this.mContext = context;

    }

    public void setDevice(GizWifiDevice device) {
        MyLog.i("app后台 device去向", "setDevice: "+device);
        mDevice = device;
        mDevice.setListener(gizWifiDeviceListener);
    }

    public GizWifiDevice getDevice() {
        MyLog.i("app后台 device去向", "getDevice: "+mDevice);
        return mDevice;
    }

    @SuppressWarnings("unchecked")
    private void getDataFromReceiveDataMap(ConcurrentHashMap<String, Object> dataMap) {
        // 已定义的设备数据点，有布尔、数值和枚举型数据

        if (dataMap.get("data") != null) {
            ConcurrentHashMap<String, Object> map = (ConcurrentHashMap<String, Object>) dataMap.get("data");
            for (String dataKey : map.keySet()) {
                if (dataKey.equals(KEY_STOP)) {
                    data_Stop = (Boolean) map.get(dataKey);
                }
                if (dataKey.equals(KEY_HOME)) {
                    data_Home = (Boolean) map.get(dataKey);
                }
                if (dataKey.equals(KEY_WORKINGAREA)) {

                    data_workingArea = (Integer) map.get(dataKey);
                }
                if (dataKey.equals(KEY_LANGUAGE)) {

                    data_Language = (Integer) map.get(dataKey);
                }
                if (dataKey.equals(KEY_WORKINGTIME)) {

                    data_WorkingTime = (byte[]) map.get(dataKey);
                }
                if (dataKey.equals(KEY_CURRENTTIME)) {

                    data_CurrentTime = (byte[]) map.get(dataKey);
                }
                if (dataKey.equals(KEY_PIN)) {

                    data_PIN = (byte[]) map.get(dataKey);
                }
                if (dataKey.equals(KEY_POWER)) {

                    data_Power = (Integer) map.get(dataKey);
                }
                if (dataKey.equals(KEY_ERROR)) {

                    data_Error = (Integer) map.get(dataKey);
                }
                if (dataKey.equals(KEY_ROBOTSTATE)) {

                    data_RobotState = (Integer) map.get(dataKey);
                }
            }
        }

        StringBuilder sBuilder = new StringBuilder();

        // 已定义的设备报警数据点，设备发生报警后该字段有内容，没有发生报警则没内容
        if (dataMap.get("alerts") != null) {
            ConcurrentHashMap<String, Object> map = (ConcurrentHashMap<String, Object>) dataMap.get("alerts");
            for (String alertsKey : map.keySet()) {
                if ((Boolean) map.get(alertsKey)) {
                    sBuilder.append("报警:" + alertsKey + "=true" + "\n");
                }
            }
        }

        // 已定义的设备故障数据点，设备发生故障后该字段有内容，没有发生故障则没内容
        if (dataMap.get("faults") != null) {
            ConcurrentHashMap<String, Object> map = (ConcurrentHashMap<String, Object>) dataMap.get("faults");
            for (String faultsKey : map.keySet()) {
                if ((Boolean) map.get(faultsKey)) {
                    sBuilder.append("故障:" + faultsKey + "=true" + "\n");
                }
            }
        }

        if (sBuilder.length() > 0) {
            sBuilder.insert(0, "[设备故障或报警]\n");
            myToast(sBuilder.toString().trim());
        }

        // 透传数据，无数据点定义，适合开发者自行定义协议自行解析
        if (dataMap.get("binary") != null) {
            byte[] binary = (byte[]) dataMap.get("binary");
            Log.i("", "Binary data:" + HexStrUtils.bytesToHexString(binary));
        }
    }

    /**
     * 发送指令,下发单个数据点的命令可以用这个方法
     *
     * <h3>注意</h3>
     * <p>
     * 下发多个数据点命令不能用这个方法多次调用，一次性多次调用这个方法会导致模组无法正确接收消息，参考方法内注释。
     * </p>
     *
     * @param key
     *            数据点对应的标识名
     * @param value
     *            需要改变的值
     */
    public void sendCommand(String key, Object value) {
        if (value == null) {
            return;
        }
        int sn = 5;
        ConcurrentHashMap<String, Object> hashMap = new ConcurrentHashMap<String, Object>();
        hashMap.put(key, value);
        // 同时下发多个数据点需要一次性在map中放置全部需要控制的key，value值
        // hashMap.put(key2, value2);
        // hashMap.put(key3, value3);
        mDevice.write(hashMap, sn);
        Log.i("liang", "下发命令：" + hashMap.toString());
    }

    public void GizWrite(byte[] sendByte) {
        String send = HexUtil.formatHexString(sendByte,true);
        MyLog.i("GizWrite", "GizWrite: "+send+"mDevice:"+mDevice);
        dataMap.put("binary", sendByte);
        mDevice.write(dataMap, 0);
    }

    public void myToast(String string) {
        if (mToast != null) {
            mToast.setText(string);
        } else {
            mToast = Toast.makeText(mContext, string, Toast.LENGTH_LONG);
        }
        mToast.show();
    }

    private GizWifiDeviceListener gizWifiDeviceListener = new GizWifiDeviceListener() {

        /** 用于设备订阅 */
        public void didSetSubscribe(GizWifiErrorCode result, GizWifiDevice device, boolean isSubscribed) {
            if (mCallback!=null) {
                mCallback.didSetSubscribe(result, device, isSubscribed);
            }
        };

        /** 用于获取设备状态 */
        public void didReceiveData(GizWifiErrorCode result, GizWifiDevice device,
                                   java.util.concurrent.ConcurrentHashMap<String, Object> dataMap, int sn) {
            getDataFromReceiveDataMap(dataMap);
            if (mCallback!=null){
                mCallback.didReceiveData(result, device, dataMap, sn);
            }

        };

        /** 用于设备硬件信息 */
        public void didGetHardwareInfo(GizWifiErrorCode result, GizWifiDevice device,
                                       java.util.concurrent.ConcurrentHashMap<String, String> hardwareInfo) {
            if (mCallback!=null){
                mCallback.didGetHardwareInfo(result, device, hardwareInfo);
            }
        };

        /** 用于修改设备信息 */
        public void didSetCustomInfo(GizWifiErrorCode result, GizWifiDevice device) {
            if (mCallback!=null){

            }
        };

        /** 用于设备状态变化 */
        public void didUpdateNetStatus(GizWifiDevice device, GizWifiDeviceNetStatus netStatus) {
            if (mCallback!=null){
                mCallback.didUpdateNetStatus(device, netStatus);
            }
        };

    };



    private myGizWifiDeviceListener mCallback;

    public void removeCallback(){
        MyLog.i("Gizcallback", "removeCallback: "+this.mCallback);
        this.mCallback = null;
    }

    public void setmCallback(myGizWifiDeviceListener mCallback) {

        MyLog.i("Gizcallback", "setmCallback: "+mCallback);
        this.mCallback = mCallback;
    }

    public void unSubcriber(){
        if (mDevice!=null){
           // mDevice.setSubscribe("4fa35c2d2fbf4259a668eb9e994d1b78",false);
            mDevice.setSubscribe(false);
        }
    }
    public interface myGizWifiDeviceListener{
        /**
         * 设备订阅回调
         *
         * @param result
         *            错误码
         * @param device
         *            被订阅设备
         * @param isSubscribed
         *            订阅状态
         */
         void didSetSubscribe(GizWifiErrorCode result, GizWifiDevice device, boolean isSubscribed);

        /**
         * 设备状态回调
         *
         * @param result
         *            错误码
         * @param device
         *            当前设备
         * @param dataMap
         *            当前设备状态
         * @param sn
         *            命令序号
         */
         void didReceiveData(GizWifiErrorCode result, GizWifiDevice device,
                                      java.util.concurrent.ConcurrentHashMap<String, Object> dataMap, int sn);

        /**
         * 设备硬件信息回调
         *
         * @param result
         *            错误码
         * @param device
         *            当前设备
         * @param hardwareInfo
         *            当前设备硬件信息
         */
         void didGetHardwareInfo(GizWifiErrorCode result, GizWifiDevice device,
                                          java.util.concurrent.ConcurrentHashMap<String, String> hardwareInfo);

        /**
         * 修改设备信息回调
         *
         * @param result
         *            错误码
         * @param device
         *            当前设备
         */
         void didSetCustomInfo(GizWifiErrorCode result, GizWifiDevice device);

        /**
         * 设备状态变化回调
         */
         void didUpdateNetStatus(GizWifiDevice device, GizWifiDeviceNetStatus netStatus);

    }

}
